package main

import (
	"fmt"
	"sort"
)

// Task task
type Task struct {
	Tasks  []byte
	Length int
}

func (t *Task) String() string {
	return fmt.Sprintf("task = {%v}, length=%v", t.Tasks, t.Length)
}

// TaskSlice Task Slice
type TaskSlice []*Task

// Len Task slice length
func (b TaskSlice) Len() int {
	return len(b)
}

// Less Task slice length
func (b TaskSlice) Less(i, j int) bool {
	return b[j].Length < b[i].Length
}

// Swap Task slice length
func (b TaskSlice) Swap(i, j int) {
	b[i], b[j] = b[j], b[i]
}

// ByteSlice Byte Slice
type ByteSlice []byte

func getValue(m map[byte]*Task) []*Task {
	values := make([]*Task, 0)
	for _, v := range m {
		values = append(values, v)
	}
	return values
}

func leastInterval(tasks []byte, n int) int {
	count := 0
	taskMap := make(map[byte]*Task)

	for i := 0; i < len(tasks); i++ {
		key := tasks[i]
		if v, ok := taskMap[key]; !ok {
			taskMap[key] = &Task{make([]byte, 0), 0}
			taskMap[key].Tasks = append(taskMap[key].Tasks, key)
			taskMap[key].Length = len(taskMap[key].Tasks)
		} else {
			v.Tasks = append(v.Tasks, key)
			v.Length = len(v.Tasks)
		}
	}
	values := TaskSlice(getValue(taskMap))

	sort.Sort(values)

	for v := range values {
		fmt.Println(values[v])
	}

	maxTaskLen := values[0].Length
	secondTaskLen := 0
	if len(values) > 1 {
		secondTaskLen = values[1].Length
	}
	tasktype := make([]ByteSlice, maxTaskLen)
	for i := 0; i < maxTaskLen; i++ {
		tasktype[i] = make(ByteSlice, 0)
	}

	for i := 0; i < len(tasks); i++ {
		index := i % maxTaskLen
		tasktype[index] = append(tasktype[index], tasks[i])
	}
	fmt.Println(tasktype)
	originlen := 0
	for i := 0; i < maxTaskLen; i++ {
		count += len(tasktype[i])
		originlen += len(tasktype[i])
		if i != maxTaskLen-1 {
			if len(tasktype[i]) < n+1 {
				gap := n + 1 - len(tasktype[i])
				fmt.Printf("gap = %v\n", gap)
				count += gap
			}
		} else {
			if secondTaskLen != 0 && maxTaskLen != secondTaskLen && count > originlen {
				fmt.Printf("count = %v\n", count)
				count -= (len(tasktype[i]) - 1)
			}
		}
	}

	return count
}

func main() {
	tasks := []byte{'A', 'A', 'A', 'A', 'A', 'A', 'B', 'C', 'D', 'E', 'F', 'G'}
	n := 2
	tasks = []byte{'A', 'A', 'A', 'B', 'B', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'}

	n = 7
	time := leastInterval(tasks, n)
	fmt.Println()
	fmt.Println(time)
}
